// vue3响应式原理
let toProxy = new WeakMap() // 弱引用映射表，放置的是原对象：代理后的对象
let toRaw = new WeakMap() //被代理过的对象：原对象

function isObject(val){
    return typeof val === 'object' && val !== null
}

function reactive(target){
    return createReactiveObject(target);

}
function createReactiveObject(target){
    if(!isObject(target)){
        return target
    }
    let proxy = toProxy.get(target)
    // 如果一个对象已经被代理了那就返回代理后的结果
    if(proxy){
        return proxy
    }
    // 防止代理过的对象再次被代理
    if(toRaw.has(target)){
        return target
    }

    let handled = {
        // receiver 代理后的对象
        get:function (target,key,receiver){
            // console.log("获取")
            // return target[key]
            // proxy reflect 反射
            let res = Reflect.get(target,key,receiver)
            // 当对象嵌套多层时，递归（多层代理）
            return isObject(res)?reactive(res):res
        },
        set:function (target,key,value,receiver){
            // target[key] = value
            // 好处是有返回值,知道是否设置成功
            let hasOwn = target.hasOwnProperty(key)
            let res = Reflect.set(target,key,value,receiver)
            if(!hasOwn){
                // 新增属性值
                console.log("新增属性值")
            }else if(target[key] !== value){
                // 修改属性值
                console.log("修改属性值")
            }
            return res
        },
        deleteProperty(target, key) {
            console.log("删除")
            let res = Reflect.deleteProperty(target,key)
            return res
        }
    }
    let observed = new Proxy(target,handled)
    toProxy.set(target,observed)
    toRaw.set(observed,target)
    return observed
}
let proxy = reactive({name:'zxw',likes:['swim','running'],sports:{m:2,n:1}})

// proxy.sports.m = 3  // 为什么这里只获取了一次，不是两次（从值中取出sports一次，然后进行赋值操作，所以只打印'获取'一次）

proxy.likes.push('2')